﻿using DataType;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using DataType.MessageType;
using MapCalclator;
using OprsSimulator.OprAttributes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OprsSimulator.Operators
{
    public class IFVOpr : IOperator, ICommonAttris, IAttackAttris, IMoveAttris, IStateAttris, IReconnaissanceAttris, IDefendAttris, ICarryingAttris
    {
        //ICommonAttris
        private int obj_id;
        private string name;
        private Color color;
        private OprType type;
        private OprSubType sub_type;
        private int value;
        private int blood;
        private int max_blood;

        public int ObjID { get => obj_id; }
        public string Name { get => name; }

        public Color Color { get => color; }

        public OprType Type { get => type; }

        public OprSubType Subtype { get => sub_type; }

        public int Value { get => value; }

        public int Blood { get => blood; set => blood = value; }

        public int MaxBlood { get => max_blood; }

        //IAttackAttris
        private bool a1;
        private List<WeaponType> carry_weapon_ids = new List<WeaponType>();
        private Dictionary<BulletType, int> remain_bullet_nums = new Dictionary<BulletType, int>();
        private Dictionary<BulletType, int> remain_bullet_nums_bk = new Dictionary<BulletType, int>();
        private bool guide_ability;
        private int weapon_cool_time;
        private int weapon_unfold_time;
        private int weapon_unfold_state;
        public bool A1 { get => a1; }

        public List<WeaponType> CarryWeaponIDs { get => carry_weapon_ids; }

        public Dictionary<BulletType, int> RemainBulletNums { get => remain_bullet_nums; set => remain_bullet_nums = value; }
        public Dictionary<BulletType, int> RemainBulletNumsBK { get => remain_bullet_nums_bk; set => remain_bullet_nums_bk = value; }

        public bool GuideAbility { get => guide_ability; }

        public int WeaponCoolTime { get => weapon_cool_time; set => weapon_cool_time = value; }
        public int WeaponUnfoldTime { get => weapon_unfold_time; set => weapon_unfold_time = value; }
        public int WeaponUnfoldState { get => weapon_unfold_state; set => weapon_unfold_state = value; }

        //IMoveAttris
        private int basic_speed;
        private MoveStateType move_state;
        private int cur_hex;
        private float cur_pos;
        private int speed;
        private int move_to_stop_remain_time;
        private bool can_to_move;
        private bool flag_force_stop;
        private bool stop;
        private List<int> move_path;
        private int tire;
        private int tire_accumulate_time;
        private bool on_board;
        private int car;
        private int launcher;
        private int get_on_remain_time;
        private List<int> get_on_partner_id;
        private int get_off_remain_time;
        private List<int> get_off_partner_id;
        private int change_state_remain_time;
        private MoveStateType target_state;

        public int BasicSpeed { get => basic_speed; }

        public MoveStateType MoveState { get => move_state; set => move_state = value; }
        public int CurHex { get => cur_hex; set => cur_hex = value; }
        public float CurPos { get => cur_pos; set => cur_pos = value; }
        public int Speed { get => speed; set => speed = value; }
        public int MoveToStopRemainTime { get => move_to_stop_remain_time; set => move_to_stop_remain_time = value; }
        public bool CanToMove { get => can_to_move; set => can_to_move = value; }
        public bool FlagForceStop { get => flag_force_stop; set => flag_force_stop = value; }
        public bool Stop { get => stop; set => stop = value; }
        public List<int> MovePath { get => move_path; set => move_path = value; }
        public int Tire { get => tire; set => tire = value; }
        public int TireAccumulateTime { get => tire_accumulate_time; set => tire_accumulate_time = value; }
        public bool OnBoard { get => on_board; set => on_board = value; }
        public int Car { get => car; set => car = value; }
        public int Launcher { get => launcher; set => launcher = value; }
        public int GetOnRemainTime { get => get_on_remain_time; set => get_on_remain_time = value; }
        public List<int> GetOnPartnerId { get => get_on_partner_id; set => get_on_partner_id = value; }
        public int GetOffRemainTime { get => get_off_remain_time; set => get_off_remain_time = value; }
        public List<int> GetOffPartnerId { get => get_off_partner_id; set => get_off_partner_id = value; }
        public int ChangeStateRemainTime { get => change_state_remain_time; set => change_state_remain_time = value; }
        public MoveStateType TargetState { get => target_state; set => target_state = value; }
        //IStateAttris
        private bool stack;
        private bool keep;
        private int keep_remain_time;
        private bool lose_control;
        private int alive_remain_time;
        public bool Stack { get => stack; set => stack = value; }
        public bool Keep { get => keep; set => keep = value; }
        public int KeepRemainTime { get => keep_remain_time; set => keep_remain_time = value; }
        public bool LoseControl { get => lose_control; set => lose_control = value; }
        public int AliveRemainTime { get => alive_remain_time; set => alive_remain_time = value; }
        //IReconnaissanceAttris
        private Dictionary<OprSubType, int> observe_distance;
        private List<int> see_enemy_bop_ids;
        public Dictionary<OprSubType, int> ObserveDistance { get => observe_distance; }

        public List<int> SeeEnemyBopIDs { get => see_enemy_bop_ids; set => see_enemy_bop_ids = value; }
        //IDefendAttris
        private ArmorType armor;
        public ArmorType Armor { get => armor; set => armor = value; }
        //ICarryingAttris
        private List<OprSubType> valid_passenger_types;
        private Dictionary<OprSubType, int> max_passenger_nums;
        private int loading_capacity;
        private List<int> passenger_ids;
        private List<int> launch_ids;
        public List<OprSubType> ValidPassengerTypes { get => valid_passenger_types; }

        public Dictionary<OprSubType, int> MaxPassengerNums { get => max_passenger_nums; }

        public int LoadingCapacity { get => loading_capacity; }

        public List<int> PassengerIDs { get => passenger_ids; set => passenger_ids = value; }
        public List<int> LaunchIDs { get => launch_ids; set => launch_ids = value; }

        public void SetUp(OperatorMsg operatorMsg)
        {
            //ICommonAttris
            obj_id = operatorMsg.obj_id;
            name = operatorMsg.name;
            color = (Color)operatorMsg.color;
            type = (OprType)operatorMsg.type;
            sub_type = (OprSubType)operatorMsg.sub_type;
            value = operatorMsg.value;
            blood = operatorMsg.blood;
            max_blood = operatorMsg.max_blood;
            //IAttackAttris
            a1 = operatorMsg.A1;
            foreach (int id in operatorMsg.carry_weapon_ids)
            {
                carry_weapon_ids.Add((WeaponType)id);
            }
            foreach (var remain_bullet_num in operatorMsg.remain_bullet_nums)
            {
                remain_bullet_nums.Add((BulletType)remain_bullet_num.Key, remain_bullet_num.Value);
            }
            foreach (var remain_bullet_num_bk in operatorMsg.remain_bullet_nums_bk)
            {
                remain_bullet_nums_bk.Add((BulletType)remain_bullet_num_bk.Key, remain_bullet_num_bk.Value);
            }
            guide_ability = operatorMsg.guide_ability;
            weapon_cool_time = operatorMsg.weapon_cool_time;
            weapon_unfold_time = operatorMsg.weapon_unfold_time;
            weapon_unfold_state = operatorMsg.weapon_unfold_state;
            //IMoveAttris
            basic_speed = operatorMsg.basic_speed;
            move_state = (MoveStateType)operatorMsg.move_state;
            cur_hex = operatorMsg.cur_hex;
            cur_pos = operatorMsg.cur_pos;
            speed = operatorMsg.speed;
            move_to_stop_remain_time = operatorMsg.move_to_stop_remain_time;
            can_to_move = operatorMsg.can_to_move;
            flag_force_stop = operatorMsg.flag_force_stop;
            stop = operatorMsg.stop;
            move_path = operatorMsg.move_path;
            tire = operatorMsg.tire;
            tire_accumulate_time = operatorMsg.tire_accumulate_time;
            on_board = operatorMsg.on_board;
            car = operatorMsg.car;
            launcher = operatorMsg.launcher;
            get_on_remain_time = operatorMsg.get_on_remain_time;
            get_on_partner_id = operatorMsg.get_on_partner_id;
            get_off_remain_time = operatorMsg.get_off_remain_time;
            get_off_partner_id = operatorMsg.get_off_partner_id;
            change_state_remain_time = operatorMsg.change_state_remain_time;
            target_state = (MoveStateType)operatorMsg.target_state;
            //IStateAttris
            stack = operatorMsg.stack;
            keep = operatorMsg.keep;
            keep_remain_time = operatorMsg.keep_remain_time;
            lose_control = operatorMsg.lose_control;
            alive_remain_time = operatorMsg.alive_remain_time;
            //IReconnaissanceAttris
            if (operatorMsg.observe_distance == null)
            {
                observe_distance = new Dictionary<OprSubType, int>
                {
                    {OprSubType.Tank, 25},
                    {OprSubType.IFV, 25},
                    {OprSubType.Infantry, 10},
                    {OprSubType.Artillery, 10},
                    {OprSubType.UGV, 25},
                    {OprSubType.Drone, 1},
                    {OprSubType.Helicopter, 25},
                    {OprSubType.CruisingMissile, 1},
                };
            }
            else
            {
                foreach (var od in operatorMsg.observe_distance)
                {
                    observe_distance.Add((OprSubType)od.Key, od.Value);
                }
            }
            see_enemy_bop_ids = operatorMsg.see_enemy_bop_ids;
            //IDefendAttris
            armor = (ArmorType)operatorMsg.armor;
            //ICarryingAttris
            valid_passenger_types = new List<OprSubType>();
            foreach (int type in operatorMsg.valid_passenger_types)
            {
                valid_passenger_types.Add((OprSubType)type);
            }
            max_passenger_nums = new Dictionary<OprSubType, int>();
            foreach(var num in operatorMsg.max_passenger_nums)
            {
                max_passenger_nums.Add((OprSubType)num.Key, num.Value);
            }
            loading_capacity = operatorMsg.loading_capacity;
            passenger_ids = operatorMsg.passenger_ids;
            launch_ids = operatorMsg.launch_ids;
        }
        public void UpdataStandaloneAttris(List<IJudgeResult> judge_results, Map map)
        {
            foreach (IJudgeResult judge_result in judge_results)
            {
                if (!judge_result.IsSuccess) continue;  // 每个子方法中不需要在检查这个条件了

                if (judge_result.ActionType == ActionType.Shoot)  // 射击裁决的信息更新移动到此处
                {
                    JudgeType type = (JudgeType)judge_result.GetType().GetProperty("Type").GetValue(judge_result);
                    if (type == JudgeType.Shoot) UpdataShootAttris(judge_result);
                }
                else if (judge_result.ActionType == ActionType.GetOn)
                {
                    UpdataGetOnAttris(judge_result);    //  战车默认为上车的目标
                }
                else
                {
                    if (judge_result.ObjID != obj_id) continue;  // 每个子方法中不需要在检查这个条件了
                    if (judge_result.ActionType == ActionType.Move) UpdataMoveAttris(judge_result, map);
                    else if (judge_result.ActionType == ActionType.ChangeState) UpdataChangeStateAttris(judge_result);
                    else if (judge_result.ActionType == ActionType.StopMove) UpdataStopMoveAttris(judge_result);
                    else if (judge_result.ActionType == ActionType.WeaponLock) UpdataWeaponLockAttris(judge_result);
                    else if (judge_result.ActionType == ActionType.WeaponUnfold) UpdataWeaponUnfoldAttris(judge_result);
                    else if (judge_result.ActionType == ActionType.GetOff) UpdataGetOffAttris(judge_result);
                }
            }
            PutForwardObservation(map);
        }

        public void UpdateAssociatedAttris(List<IOperator> oprs, Map map)
        {
            UpdataStackAttris(oprs);
            UpdataSeeEnemyAttris(oprs, map);
            JudgeMoveObstruction(oprs);
            GetOnAndOffMonitor(oprs);
        }
        public Dictionary<int, List<ActionMsg>> ConfirmValidActions(List<OperatorMsg> oprs, CityMsg[] cities, Map map, ShootJudgeTable shootJudgeTable)
        {
            Dictionary<int, List<ActionMsg>> individualValidActions = new Dictionary<int, List<ActionMsg>>();

            // 判断算子是否能机动
            bool move_flag = true;  // 能够机动的标识
            List<ActionMsg> move_action = new List<ActionMsg>();
            if (speed > 0) move_flag = false;   //未停下的算子不可机动
            if (get_off_remain_time > 0 || get_on_remain_time > 0) move_flag = false;   //上下车过程中不可执行其它命令
            if (!can_to_move && move_to_stop_remain_time > 0) move_flag = false;
            else if (change_state_remain_time > 0)  // 如果正处于状态转换过程中
            {
                if (target_state == MoveStateType.March || target_state == MoveStateType.Shelt) move_flag = false;
                if (move_state == MoveStateType.March && target_state == MoveStateType.Normal) move_flag = false;
            }
            if (move_flag)
            {
                move_action.Add(new ActionMsg { type = (int)ActionType.Move, obj_id = obj_id });
                individualValidActions.Add((int)ActionType.Move, move_action);
            }

            // 判断算子是否能射击
            bool shoot_flag = true;  // 不能射击的标识
            List<ActionMsg> shoot_action = new List<ActionMsg>();
            if (weapon_cool_time > 0) shoot_flag = false;
            else if(get_off_remain_time > 0 || get_on_remain_time > 0) shoot_flag = false;   //上下车过程中不可执行其它命令
            else if (weapon_unfold_time > 0) shoot_flag = false;  // 武器正在展开或折叠
            else if (weapon_unfold_state == 0) shoot_flag = false;  // 武器处于锁定状态
            else if (move_state == MoveStateType.March) shoot_flag = false;  // 行军状态不可射击
            else if (target_state == MoveStateType.March && change_state_remain_time > 0) shoot_flag = false;  // 行军状态转换过程中
            else if (!a1 && target_state == MoveStateType.Shelt && change_state_remain_time > 0) shoot_flag = false;
            else if (!a1 && speed > 0) shoot_flag = false;
            else if (!a1 && !stop) shoot_flag = false;
            else if (see_enemy_bop_ids.Count == 0) shoot_flag = false;  // 视野范围内没有敌方算子
            else
            {
                for (int i = 0; i < see_enemy_bop_ids.Count(); i++)
                //foreach (int enemy_id in see_enemy_bop_ids)
                {
                    int enemy_id = see_enemy_bop_ids[i];
                    // 逐个判断是否能对enemy_id的敌方算子实施射击
                    OperatorMsg enemy;
                    foreach (OperatorMsg oper in oprs)
                    {
                        if (oper.obj_id == enemy_id)
                        {
                            enemy = oper;
                            foreach (WeaponType weapon_id in carry_weapon_ids)
                            {

                                bool can_see = map.CanSeeTerrain(type, (OprType)enemy.type, cur_hex, enemy.cur_hex, (OprSubType)enemy.sub_type, observe_distance, (MoveStateType)enemy.move_state);
                                int distance = map.GetDistance(cur_hex, enemy.cur_hex);
                                int attack_level = shootJudgeTable.CalcAttackLevel(can_see, remain_bullet_nums, weapon_id, (OprType)enemy.type, distance, blood);
                                if (attack_level > 0)
                                {
                                    shoot_action.Add(
                                        new ActionMsg
                                        {
                                            type = (int)ActionType.Shoot,
                                            obj_id = obj_id,
                                            target_obj_id = enemy_id,
                                            weapon_id = (int)weapon_id,
                                            attack_level = attack_level
                                        }
                                        );
                                }
                            }
                        }
                    }
                }
            }
            if (shoot_flag)
            {
                if (shoot_action.Count > 0)
                {
                    individualValidActions.Add((int)ActionType.Shoot, shoot_action);
                }
            }

            // 判断是否能夺控
            foreach (CityMsg city in cities)
            {
                if (cur_hex == city.coord && (int)color != city.flag)
                {
                    bool enemy_neighbor = false;
                    foreach (OperatorMsg ob in oprs)
                    {
                        if (ob.color == (int)color) continue;
                        if (ob.type != (int)OprType.Airplane && ob.type != (int)OprType.Fortification)
                        {
                            if (map[city.coord / 100, city.coord % 100].neighbors.Contains(ob.cur_hex))
                            {
                                enemy_neighbor = true;
                                break;
                            }
                        }
                    }

                    if (!enemy_neighbor)  // 能夺控的条件：夺控点周围不能由敌人
                    {
                        List<ActionMsg> occupy_action = new List<ActionMsg>();
                        occupy_action.Add(
                            new ActionMsg { type = (int)ActionType.Occupy, obj_id = obj_id }
                            );
                        individualValidActions.Add((int)ActionType.Occupy, occupy_action);
                        break;
                    }
                }
            }


            // 判断是否能切换状态
            List<ActionMsg> change_state_action = new List<ActionMsg>();
            // 1.判断能否转正常机动状态
            if ((move_state == MoveStateType.March || move_state == MoveStateType.HalfSpeed) && change_state_remain_time <= 0)
            {
                if (stop | speed <= 0.0)  // 只要停下来就能切换成正常机动状态
                {
                    change_state_action.Add(
                    new ActionMsg { type = (int)ActionType.ChangeState, obj_id = obj_id, target_state = (int)MoveStateType.Normal }
                    );
                }
            }
            // 2.判断能否转行军状态
            if ((move_state == MoveStateType.March || move_state == MoveStateType.HalfSpeed) && change_state_remain_time <= 0 && get_on_remain_time <= 0 && get_off_remain_time <= 0)  // 判断是否处于正常状态
            {
                if (weapon_unfold_state == 0 && weapon_unfold_time <= 0)  // 判断是否武器处于锁定状态
                {
                    if (map[cur_hex / 100, cur_hex % 100].roads.Max() > 0)  // 判断是否在道路上
                    {
                        if (stop | speed <= 0.0)  // 必须已经停下来了
                        {
                            change_state_action.Add(
                                new ActionMsg { type = (int)ActionType.ChangeState, obj_id = obj_id, target_state = (int)MoveStateType.March }
                                );
                        }
                    }
                }
            }
            // 3.判断能否转掩蔽状态
            if (!keep) // 不能处于压制状态
            {
                if ((move_state == MoveStateType.March || move_state == MoveStateType.HalfSpeed) && change_state_remain_time <= 0 && get_on_remain_time <= 0 && get_off_remain_time <= 0)  // 判断是否处于正常状态
                {
                    if (stop | speed <= 0.0)  // 必须已经停下来了
                    {
                        change_state_action.Add(
                            new ActionMsg { type = (int)ActionType.ChangeState, obj_id = obj_id, target_state = (int)MoveStateType.Shelt }
                            );
                    }
                }
            }
            // 4.判断能否转半速状态
            if (move_state == MoveStateType.Normal && change_state_remain_time <= 0)  // 判断是否处于正常状态
            {
                if (stop | speed <= 0.0)  // 停下来
                {
                    change_state_action.Add(
                    new ActionMsg { type = (int)ActionType.ChangeState, obj_id = obj_id, target_state = (int)MoveStateType.HalfSpeed }
                    );
                }
            }
            // 如果change_state_action不为空
            if (change_state_action.Count > 0) individualValidActions.Add((int)ActionType.ChangeState, change_state_action);

            // 判断能否停止机动
            if (speed > 0)
            {
                List<ActionMsg> stop_move_action = new List<ActionMsg>();
                stop_move_action.Add(new ActionMsg { type = (int)ActionType.StopMove, obj_id = obj_id });
                individualValidActions.Add((int)ActionType.StopMove, stop_move_action);
            }

            // 判断能否锁定武器
            if (weapon_unfold_state == 1)
            {
                if (stop & speed <= 0 & move_to_stop_remain_time <= 0 & weapon_unfold_time <= 0 && get_on_remain_time <= 0 && get_off_remain_time <= 0)
                {
                    List<ActionMsg> weapon_lock_action = new List<ActionMsg>();
                    weapon_lock_action.Add(new ActionMsg { type = (int)ActionType.WeaponLock, obj_id = obj_id });
                    individualValidActions.Add((int)ActionType.WeaponLock, weapon_lock_action);
                }
            }

            // 判断能否展开武器
            if (weapon_unfold_state == 0)
            {
                if (stop & speed <= 0 & move_to_stop_remain_time <= 0 & weapon_unfold_time <= 0 && get_on_remain_time <= 0 && get_off_remain_time <= 0)
                {
                    List<ActionMsg> weapon_unfold_action = new List<ActionMsg>();
                    weapon_unfold_action.Add(new ActionMsg { type = (int)ActionType.WeaponUnfold, obj_id = obj_id });
                    individualValidActions.Add((int)ActionType.WeaponUnfold, weapon_unfold_action);
                }
            }

            //判断能否下车
            if (passenger_ids.Count > 0) //&& get_on_remain_time <= 0)
            {
                if(stop && !keep && move_state != MoveStateType.March)
                {
                    List<ActionMsg> get_off_action = new List<ActionMsg>();
                    foreach (int id in passenger_ids)
                    {
                        if (!get_off_partner_id.Contains(id))
                        {
                            get_off_action.Add(new ActionMsg { type = (int)ActionType.GetOff, obj_id = obj_id, target_obj_id = id });
                        }
                    }                  
                    if(get_off_action.Count > 0) individualValidActions.Add((int)ActionType.GetOff, get_off_action);
                }
            }
            return individualValidActions;
        }
        private void PutForwardObservation(Map map)
        {
            // 修改机动属性
            if (speed > 0 && move_path.Count > 0)
            {
                float percetage = (float)speed / 3.6f / (float)map.Width;
                cur_pos += percetage;
                if (cur_pos >= 1)  // 到达了下一格
                {
                    cur_pos = 0;
                    cur_hex = move_path[0];
                    move_path.RemoveAt(0);
                    if (move_path.Count <= 0)  // 转为停止
                    {
                        speed = 0;
                        move_to_stop_remain_time = 76;
                    }
                    else
                    {
                        MoveMode mode;
                        float basicSpeed;
                        if (move_state == MoveStateType.March)
                        {
                            mode = MoveMode.VehicleMarch;
                            // TODO 公路分类：乡村路（黑色线）40千米/小时，一般公路（红色线）60千米/小时，等级公路（黄色线）90千米/小时
                            basicSpeed = (float)90;  // 行军的标准速度
                        }
                        else if (move_state == MoveStateType.Normal)
                        {
                            mode = MoveMode.VehicleMove;
                            basicSpeed = basic_speed;    //(float)36;    // 正常机动速度
                        }
                        else if (move_state == MoveStateType.HalfSpeed)
                        {
                            mode = MoveMode.VehicleMove;
                            basicSpeed = basic_speed / 2;//(float)18;    
                        }
                        else
                        {
                            Trace.TraceWarning($"持续机动属性更新失败：算子{obj_id}机动状态有误");
                            return;
                        }
                        speed = (int)(basicSpeed / map.GetHexCosts(cur_hex / 100, cur_hex % 100, mode)[move_path[0]]);
                    }
                }
            }
            // 停止机动
            if (flag_force_stop)
            {
                if (speed == 0)
                {
                    if (can_to_move)
                    {
                        flag_force_stop = false;
                    }
                }
                else if (cur_pos <= 0)
                {
                    if (move_path == null) move_path = new List<int>();
                    else move_path.Clear();
                    speed = 0;
                    move_to_stop_remain_time = 76;
                    can_to_move = false;
                }
            }
            // 75秒倒计时
            if (move_to_stop_remain_time > 0)  // 停止倒计时
            {
                move_to_stop_remain_time--;
                if (move_to_stop_remain_time <= 0)
                {
                    can_to_move = true;
                    flag_force_stop = false;
                    stop = true;
                }
            }
            if (change_state_remain_time > 0)  // 切换状态倒计时
            {
                if (keep && target_state == MoveStateType.Shelt)    //被压制，中断掩蔽
                {
                    change_state_remain_time = 0;
                    target_state = move_state;
                }
                else
                {
                    change_state_remain_time--;
                    if (change_state_remain_time <= 0)
                    {
                        move_state = target_state;
                    }
                }
            }
            if (weapon_cool_time > 0)  // 武器冷却倒计时
            {
                weapon_cool_time--;
            }
            if (weapon_unfold_time > 0)  // 武器展开/锁定倒计时
            {
                weapon_unfold_time--;
                if (weapon_unfold_time <= 0)
                {
                    weapon_unfold_state = 1 - weapon_unfold_state;
                }
            }
            if (get_on_remain_time > 0)   //上车倒计时
            {
                if (keep)
                {
                    get_on_remain_time = 0;
                    get_on_partner_id.Clear();
                }
                else if (get_on_partner_id.Count <= 0)  //上车算子都被压制，或者都已经完成上车
                {
                    get_on_remain_time = 0;
                }
                else
                {
                    get_on_remain_time--;
                    if (get_on_remain_time <= 0)
                    {
                        foreach (int id in get_on_partner_id)
                        {
                            passenger_ids.Add(id);
                            if (launch_ids.Contains(id)) launch_ids.Remove(id);
                        }
                        get_on_partner_id.Clear();
                    }
                }
            }
            if (get_off_remain_time > 0)    //下车倒计时
            {
                if (keep)
                {
                    get_off_remain_time = 0;
                    get_off_partner_id.Clear();
                }
                else if (get_off_partner_id.Count <= 0) //完成下车
                {
                    get_off_remain_time = 0;
                }
                else
                {
                    get_off_remain_time--;
                    if (get_off_remain_time <= 0)
                    {
                        foreach (int id in get_off_partner_id)
                        {
                            launch_ids.Add(id);
                            if (passenger_ids.Contains(id)) passenger_ids.Remove(id);
                        }
                        get_off_partner_id.Clear();
                    }
                }
            }
            if (keep_remain_time > 0)//压制倒计时
            {
                keep_remain_time--;
                if (keep_remain_time <= 0)
                {
                    keep = false;
                }
            }
        }
        private void UpdataMoveAttris(IJudgeResult judge_result, Map map)
        {
            if (judge_result.ActionType != ActionType.Move)
            {
                return;
            }

            MoveJudgeResult moveJudgeResult = (MoveJudgeResult)judge_result;
            //修改算子属性
            MoveMode mode;
            float basicSpeed;
            if (move_state == MoveStateType.March)
            {
                mode = MoveMode.VehicleMarch;
                // TODO 公路分类：乡村路（黑色线）40千米/小时，一般公路（红色线）60千米/小时，等级公路（黄色线）90千米/小时
                basicSpeed = (float)90;  // 行军的标准速度
            }
            else if (move_state == MoveStateType.Normal || move_state == MoveStateType.Shelt)
            {
                mode = MoveMode.VehicleMove;
                basicSpeed = basic_speed;    //(float)36;    // 正常机动速度
            }
            else if (move_state == MoveStateType.HalfSpeed)
            {
                mode = MoveMode.VehicleMove;
                basicSpeed = basic_speed / 2;//(float)18;    
            }
            else
            {
                Trace.TraceWarning($"机动裁决结果更新失败：算子{obj_id}机动状态有误");
                return;
            }
            if (move_state == MoveStateType.Shelt) move_state = MoveStateType.Normal;
            speed = (int)(basicSpeed / map.GetHexCosts(cur_hex / 100, cur_hex % 100, mode)[moveJudgeResult.MovePath[0]]);//cost[mode][cur_hex / 100][cur_hex % 100][moveJudgeResult.MovePath[0]];  // 修改速度（后面还会重复赋值）
            stop = false;
            move_path = moveJudgeResult.MovePath;
            move_to_stop_remain_time = 0;  // 一切状态切换都取消        move_to_stop_remain_time
        }
        private void UpdataChangeStateAttris(IJudgeResult judge_result)
        {
            if (judge_result.ActionType != ActionType.ChangeState)
            {
                return;
            }
            ChangeStateJudgeResult changeStateJudgeResult = (ChangeStateJudgeResult)judge_result;
            target_state = changeStateJudgeResult.TargetState;
            if (move_state == MoveStateType.Shelt && target_state == MoveStateType.Normal) move_state = target_state;
            else if (target_state == MoveStateType.HalfSpeed) move_state = target_state;
            else change_state_remain_time = 76;
        }
        private void UpdataStopMoveAttris(IJudgeResult judge_result)
        {
            if (judge_result.ActionType != ActionType.StopMove)
            {
                return;
            }
            flag_force_stop = true;
        }
        private void UpdataWeaponLockAttris(IJudgeResult judge_result)
        {
            if (judge_result.ActionType != ActionType.WeaponLock)
            {
                return;
            }
            weapon_unfold_time = 76;
        }
        private void UpdataWeaponUnfoldAttris(IJudgeResult judge_result)
        {
            if (judge_result.ActionType != ActionType.WeaponUnfold)
            {
                return;
            }
            weapon_unfold_time = 76;
        }
        private void UpdataGetOffAttris(IJudgeResult judge_result)
        {
            if (judge_result.ActionType != ActionType.GetOff) return;

            GetOffJudgeResult getOffJudgeResult = (GetOffJudgeResult) judge_result;
            get_off_partner_id.Add(getOffJudgeResult.TargetObjID);
            get_off_remain_time = 76;
        }
        private void UpdataShootAttris(IJudgeResult judge_result)
        {
            JudgeType type = (JudgeType)judge_result.GetType().GetProperty("Type").GetValue(judge_result);
            if (type != JudgeType.Shoot)
            {
                return;
            }
            if (judge_result.ActionType != ActionType.Shoot)
            {
                return;
            }

            //bool isShooting = (bool)judge_result.GetType().GetProperty("IsShooting").GetValue(judge_result);
            //if (isShooting)
            //{
            ShootingJudgeResult shootingJudgeResult = (ShootingJudgeResult)judge_result;
            if (shootingJudgeResult.ObjID == obj_id) //return;
            {
                remain_bullet_nums[shootingJudgeResult.BulletType]--;
                weapon_cool_time = 76;
                if (move_state == MoveStateType.Shelt)
                {
                    move_state = MoveStateType.Normal;
                }
            }
            //}
            //else
            //{
            //ShootedJudgeResult shootedJudgeResult = (ShootedJudgeResult)judge_result;
            else if (shootingJudgeResult.TargetObjID == obj_id) //return;
            {
                if (blood > shootingJudgeResult.Damage)
                {
                    blood -= shootingJudgeResult.Damage;
                    keep = true;
                    keep_remain_time = 151;
                    if (change_state_remain_time > 0 && target_state == MoveStateType.Shelt)//被压制，中断掩蔽
                    {
                        change_state_remain_time = 0;
                        target_state = move_state;
                    }
                    if (get_on_remain_time > 0)//被压制，中断上车
                    {
                        get_on_remain_time = 0;
                        get_on_partner_id.Clear();
                    }
                    if (get_off_remain_time > 0)//被压制，中断下车
                    {
                        get_off_remain_time = 0;
                        get_off_partner_id.Clear();
                    }
                }
                else blood = 0;
            }
            else return;
            //}
        }
        private void UpdataGetOnAttris(IJudgeResult judge_result)
        {
            if (judge_result.ActionType != ActionType.GetOn) return;

            GetOnJudgeResult getOnJudgeResult = (GetOnJudgeResult)judge_result;
            if (getOnJudgeResult.TargetObjID != obj_id) return;
            get_on_partner_id.Add(getOnJudgeResult.ObjID);
            get_on_remain_time = 76;
        }
        private void UpdataStackAttris(List<IOperator> oprs)
        {
            int stack_count = 0;
            for (int i = 0; i < oprs.Count; i++)
            {
                if (!typeof(IMoveAttris).IsAssignableFrom(oprs[i].GetType())) continue;

                int other_hex = (int)oprs[i].GetType().GetProperty("CurHex").GetValue(oprs[i]);
                if (cur_hex == other_hex)
                {
                    Color other_color = (Color)oprs[i].GetType().GetProperty("Color").GetValue(oprs[i]);
                    OprType other_type = (OprType)oprs[i].GetType().GetProperty("Type").GetValue(oprs[i]);
                    if (color == other_color && (other_type == OprType.Vehicle || other_type == OprType.Infantry)) stack_count++;
                }
            }
            if (stack_count > 1) stack = true;
            else stack = false;
        }
        private void UpdataSeeEnemyAttris(List<IOperator> oprs, Map map)
        {
            if (observe_distance == null) return;

            if (see_enemy_bop_ids == null) see_enemy_bop_ids = new List<int>();
            else see_enemy_bop_ids.Clear();
            for (int i = 0; i < oprs.Count; i++)
            {
                if (!typeof(ICommonAttris).IsAssignableFrom(oprs[i].GetType()) ||
                    !typeof(IMoveAttris).IsAssignableFrom(oprs[i].GetType())) continue;

                Color enemy_color = (Color)oprs[i].GetType().GetProperty("Color").GetValue(oprs[i]);
                OprType enemy_type = (OprType)oprs[i].GetType().GetProperty("Type").GetValue(oprs[i]);
                int enemy_hex = (int)oprs[i].GetType().GetProperty("CurHex").GetValue(oprs[i]);
                OprSubType enemy_sub_type = (OprSubType)oprs[i].GetType().GetProperty("Subtype").GetValue(oprs[i]);
                MoveStateType enemy_move_state = (MoveStateType)oprs[i].GetType().GetProperty("MoveState").GetValue(oprs[i]);

                if (color == enemy_color) continue;

                if (map.CanSeeTerrain(type, enemy_type, cur_hex, enemy_hex, enemy_sub_type, observe_distance, enemy_move_state))
                {
                    see_enemy_bop_ids.Add(oprs[i].ObjID);
                }
            }
        }
        private void JudgeMoveObstruction(List<IOperator> oprs)
        {
            if (speed > 0 && move_path.Count > 0)
            {
                int nextHexStackCount = 0;
                foreach (IOperator op in oprs)
                {
                    if (!typeof(IMoveAttris).IsAssignableFrom(op.GetType()) || !typeof(ICommonAttris).IsAssignableFrom(op.GetType())) continue;
                    //是否在下一格
                    int opHex = (int)op.GetType().GetProperty("CurHex").GetValue(op);
                    if (opHex != move_path[0]) continue;
                    //是否是地面算子
                    OprType opType = (OprType)op.GetType().GetProperty("Type").GetValue(op);
                    if (opType == OprType.Vehicle || opType == OprType.Infantry)
                    {
                        //行军阻塞判断
                        if (move_state == MoveStateType.March)
                        {
                            MoveStateType opMoveState = (MoveStateType)op.GetType().GetProperty("MoveState").GetValue(op);
                            if (opMoveState == MoveStateType.March)//行军且静止
                            {
                                bool opStop = (bool)op.GetType().GetProperty("Stop").GetValue(op);
                                if (opStop)
                                {
                                    cur_pos = 0;
                                    return;
                                }
                            }
                            else
                            {
                                cur_pos = 0;
                                return;
                            }
                        }
                        //堆叠4个阻塞判断
                        Color opColor = (Color)op.GetType().GetProperty("Color").GetValue(op);
                        if (color == opColor) nextHexStackCount++;
                    }
                }
                //六角格内已存在4个本方地面单位，则格外本方地面单位不能再进入或通过该六角格。
                if (nextHexStackCount >= 4)
                {
                    cur_pos = 0;
                }
            }
        }
        private void GetOnAndOffMonitor(List<IOperator> oprs)
        {
            if (get_on_partner_id == null) get_on_partner_id = new List<int>();
            if (get_off_partner_id == null) get_off_partner_id = new List<int>();
            //检测上车的算子是否被压制，被压制就从get_on_partner_id中移除
            foreach (IOperator op in oprs)
            {
                if (get_on_partner_id.Contains(op.ObjID))
                {
                    if (!typeof(IMoveAttris).IsAssignableFrom(op.GetType()) || !typeof(ICommonAttris).IsAssignableFrom(op.GetType())) continue;

                    bool opKeep = (bool)op.GetType().GetProperty("Keep").GetValue(op);
                    if (opKeep)
                    {
                        get_on_partner_id.Remove(op.ObjID);
                    }
                }
            }
            //目标算子完成上车
            foreach (IOperator op in oprs)
            {
                if (get_on_partner_id.Contains(op.ObjID))
                {
                    if (!typeof(IMoveAttris).IsAssignableFrom(op.GetType()) || !typeof(ICommonAttris).IsAssignableFrom(op.GetType())) continue;

                    int opCar = (int)op.GetType().GetProperty("Car").GetValue(op);
                    bool opOnBroad = (bool)op.GetType().GetProperty("OnBoard").GetValue(op);
                    if (opOnBroad && opCar == obj_id)
                    {
                        passenger_ids.Add(op.ObjID);
                        if (launch_ids.Contains(op.ObjID)) launch_ids.Remove(op.ObjID);
                        get_on_partner_id.Remove(op.ObjID);//完成上车，移除
                    }
                }
            }
            //目标算子完成下车
            foreach (IOperator op in oprs)
            {
                if (get_off_partner_id.Contains(op.ObjID))
                {
                    if (!typeof(IMoveAttris).IsAssignableFrom(op.GetType()) || !typeof(ICommonAttris).IsAssignableFrom(op.GetType())) continue;

                    int opLauncher = (int)op.GetType().GetProperty("Launcher").GetValue(op);
                    bool opOnBroad = (bool)op.GetType().GetProperty("OnBoard").GetValue(op);
                    if (!opOnBroad && opLauncher == obj_id)
                    {
                        launch_ids.Add(op.ObjID);
                        if (passenger_ids.Contains(op.ObjID)) passenger_ids.Remove(op.ObjID);
                        get_off_partner_id.Remove(op.ObjID);//完成下车，移除
                    }
                }
            }
        }
    }
}
